/** PatientPanel */
package client.ui.panel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import client.ClientManager;
import client.EventBus;
import client.events.ViewHistory;
import client.service.PatientService;
import client.service.UserService;
import domain.admin.Admin;
import domain.doctor.Doctor;
import domain.exception.ValidationException;
import domain.nurse.Nurse;
import domain.patient.Patient;
import domain.permissions.Permission;
import domain.user.SystemUser;

/**
 * @author jessienewman
 * @version $Revision: 1.0 $
 */
public class PatientPanel extends DefaultPanel {

	/**
	 * Field user.
	 */
	private SystemUser user;

	/**
	 * Field canEdit.
	 */
	private boolean canEdit;

	/**
	 * Field center.
	 */
	private JPanel center;

	/**
	 * Field history.
	 */
	/**
	 * Field save.
	 */
	/**
	 * Field reset.
	 */
	private JButton reset, save, history;

	/**
	 * Field password2Text.
	 */
	/**
	 * Field passwordText.
	 */
	/**
	 * Field usernameText.
	 */
	/**
	 * Field allergiesText.
	 */
	/**
	 * Field insuranceText.
	 */
	/**
	 * Field emailText.
	 */
	/**
	 * Field addressText.
	 */
	/**
	 * Field dobText.
	 */
	/**
	 * Field nameLast.
	 */
	/**
	 * Field nameMiddle.
	 */
	/**
	 * Field nameFirst.
	 */
	private JTextField nameFirst, nameMiddle, nameLast, 
	dobText, addressText, emailText, insuranceText, allergiesText, 
	usernameText, passwordText, password2Text;

	/**
	 * Field allergies. */
	/** Field insurance. */
	/** Field email. */
	/** Field address.	 */
	/** Field dob. */
	/** Field allergiesLabel. */
	/** Field insuranceLabel. */
	/**Field emailLabel. */
	/** Field addressLabel. */
	/** Field dobLabel. */
	private JLabel dobLabel, addressLabel, emailLabel, insuranceLabel, allergiesLabel, 
	dob, address, email, insurance, allergies, name;

	/**
	 * Field userType.
	 */
	private JComboBox userType;

	/**
	 * Field error.
	 */
	private JLabel error;

	/**
	 * Field errorFontError.
	 */
	/**
	 * Field errorFontSave.
	 */
	private Font errorFontSave, errorFontError;

	/**
	 * Field visible.
	 */
	/**
	 * Field admin.
	 */
	/**
	 * Field newUser.
	 */
	private boolean newUser, admin, isVisible;

	/**
	 * Field sdf.
	 */
	private SimpleDateFormat sdf;

	/**
	 * Field active.
	 */
	private JCheckBox active;

	/**
	 * Constructor for PatientPanel.
	 */
	public PatientPanel() {
		canEdit = false;
		admin = false;
		center = new JPanel();
		center.setLayout(new GridBagLayout());
		add(center, BorderLayout.CENTER);
	}

	/**
	 * Method addUser.
	 * @param user SystemUser
	 */
	public void addUser(SystemUser user) {
		if (user == null) {
			user = new Patient("", "", "", "", "", null, "", ""); // $codepro.audit.disable questionableAssignment
			this.newUser = true;
		} else {
			this.newUser = false;
		}
		this.user = user;

		center.removeAll();

		GridBagConstraints c = new GridBagConstraints();

		String[] types = new String[4]; // $codepro.audit.disable numericLiterals
		types[0] = "Patient";
		types[1] = "Nurse";
		types[2] = "Doctor"; // $codepro.audit.disable numericLiterals
		types[3] = "Administrator"; // $codepro.audit.disable numericLiterals
		userType = new JComboBox(types);
		userType.setSelectedIndex(0);
		userType.addActionListener(new ActionListener () {
			@Override
			public void actionPerformed(ActionEvent event) {
				if (userType.getSelectedIndex() == 0) {
					isVisible = true;
				} else {
					isVisible = false;
				}
				dobLabel.setVisible(isVisible);
				dobText.setVisible(isVisible);
				dob.setVisible(isVisible);
				emailLabel.setVisible(isVisible);
				emailText.setVisible(isVisible);
				email.setVisible(isVisible);
				addressLabel.setVisible(isVisible);
				addressText.setVisible(isVisible);
				address.setVisible(isVisible);
				allergiesLabel.setVisible(isVisible);
				allergiesText.setVisible(isVisible);
				allergies.setVisible(isVisible);
				insuranceLabel.setVisible(isVisible);
				insuranceText.setVisible(isVisible);
				insurance.setVisible(isVisible);

			}
		});

		setupFields();

		addToPanel(c);

		reset.addActionListener(new ButtonListener());
		save.addActionListener(new ButtonListener());
		history.addActionListener(new ButtonListener());
	}

	/**
	 * Method updateUser.
	 * @param userId Integer
	 */
	public void updateUser(Integer userId) {
		super.updateUser(userId);
		canEdit = ClientManager.SESSION.hasPermission(Permission.EDIT_PATIENT);
		admin = ClientManager.SESSION.hasPermission(Permission.ADMIN);
	}

	/**
	 * returns the super's toString

	 * @return String super's toString */
	public String toString() {
		return super.toString();
	}

	/**
	 * @author jessienewman
	 */
	private class ButtonListener implements ActionListener { // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString
		/**
		 * Method actionPerformed.
		 * @param event ActionEvent

		 * @see java.awt.event.ActionListener#actionPerformed(ActionEvent) */
		public void actionPerformed(ActionEvent event) {
			if (event.getSource().equals(reset)) {
				reset();
			} else if (event.getSource().equals(save)) {
				if (newUser) {
					error.setText("");
					try {
						switch (userType.getSelectedIndex()) {
						case 0:
							user = new Patient();
							break;
						case 1:
							user = new Nurse(null, null, null);
							break;
						case 2: 
							user = new Doctor(null, null, null);
							break;
						case 3:
							user = new Admin(null, null, null);
							break;
						default:
							break;
						}
						saveUser();
					} catch(ValidationException ve) {
						error.setForeground(Color.RED);
						error.setFont(errorFontError);
						error.setText(ve.getExceptionText());
					}
				} else {
					try {
						UserService.modifyName(user.getUserId(), nameFirst.getText(), 
								nameMiddle.getText(), nameLast.getText());
						UserService.setActive(user.getUserId(), !active.isSelected());
						if (user instanceof Patient) {
							PatientService.modifyDOB(user.getUserId(), dobText.getText());
							PatientService.modifyAllergies(user.getUserId(), allergiesText.getText());
							PatientService.modifyInsurance(user.getUserId(), insuranceText.getText());
							PatientService.modifyContact(user.getUserId(), addressText.getText(), 
									emailText.getText());
						}
						error.setForeground(Color.BLACK);
						error.setFont(errorFontSave);
						error.setText("User Saved");
					} catch (ValidationException ve) {
						error.setForeground(Color.RED);
						error.setFont(errorFontError);
						error.setText(ve.getExceptionText());
					}
				}
			} else if (event.getSource().equals(history)) {
				EventBus.BUS.fireEvent(new ViewHistory((Patient) user));
			}
		}

		/**
		 * Method reset.
		 */
		private void reset() {
			nameFirst.setText(user.getNameFirst());
			nameMiddle.setText(user.getNameMiddle());
			nameLast.setText(user.getNameLast());
			sdf = new SimpleDateFormat("MMMMM dd, yyyy");
			if (newUser || !(user instanceof Patient)) {
				dobText.setText("");
				addressText.setText("");
				emailText.setText("");
				insuranceText.setText("");
				allergiesText.setText("");
			} else if (user instanceof Patient){
				dobText.setText(sdf.format(((Patient) user).getDateOfBirth()));
				addressText.setText(((Patient) user).getAddress());
				emailText.setText(((Patient) user).getEmail());
				insuranceText.setText(((Patient) user).getInsurance());
				allergiesText.setText(((Patient) user).getAllergies());
			}
		}

		/**
		 * Method saveUser.
		 * @throws ValidationException
		 */
		private void saveUser() throws ValidationException {
			user.setUsername(usernameText.getText());
			user.setNameFirst(nameFirst.getText());
			user.setNameLast(nameLast.getText());
			user.setNameMiddle(nameMiddle.getText());
			user.setPassword(passwordText.getText());
			user.setActive(!active.isSelected());
			if (userType.getSelectedIndex() == 0) {
				((Patient) user).setAddress(addressText.getText());
				((Patient) user).setEmail(emailText.getText());
				((Patient) user).setAllergies(allergiesText.getText());
				((Patient) user).setPassword(passwordText.getText()); 
				
				if (!dobText.getText().isEmpty()) {
					((Patient) user).setDateOfBirth(new Date(dobText.getText()));
				}
				//work with Password2
				//((Patient)user).setDateOfBirth(dobText.getText());
			}
			int userId = UserService.addUser(user, usernameText.getText(), 
					passwordText.getText(), password2Text.getText());
			user.setUserId(userId);
			if (user instanceof Patient) {
				PatientService.modifyDOB(user.getUserId(), dobText.getText());
			}
			error.setForeground(Color.BLACK);
			error.setFont(errorFontSave);
			error.setText("User Saved");
			newUser = false;
			usernameText.setEditable(false);
			passwordText.setEditable(false);
			password2Text.setEditable(false);
		}
	}

	/**
	 * Sets values of fields to add to panel
	 */
	public void setupFields() {
		usernameText = new JTextField("");
		passwordText = new JPasswordField("");
		password2Text = new JPasswordField("");

		active = new JCheckBox("Lock Account");
		active.setSelected(!user.isActive());

		name = new JLabel(user.getNameFirst() + " " + 
				user.getNameMiddle() + " " + user.getNameLast());
		nameFirst = new JTextField(user.getNameFirst());
		nameMiddle = new JTextField(user.getNameMiddle());
		nameLast = new JTextField(user.getNameLast());

		sdf = new SimpleDateFormat("MMMMM dd, yyyy");
		dobLabel = new JLabel("DOB*: ");
		if (user instanceof Patient) {
			dob = (((Patient) user).getDateOfBirth() != null) ? 
					new JLabel(sdf.format(((Patient) user).getDateOfBirth())) : 
						new JLabel("");
		} else {
			dob = new JLabel("");
		}
		dobText = new JTextField(dob.getText());

		addressLabel = new JLabel("Address: ");
		if (user instanceof Patient) {
			address = new JLabel(((Patient) user).getAddress());
		} else {
			address = new JLabel("");
		}
		addressText = new JTextField(address.getText());

		emailLabel = new JLabel("Email: ");
		if (user instanceof Patient) {
			email = new JLabel(((Patient) user).getEmail());
		} else {
			email = new JLabel("");
		}
		emailText = new JTextField(email.getText());

		insuranceLabel = new JLabel("Insurance: ");
		if (user instanceof Patient) {
			insurance = new JLabel(((Patient) user).getInsurance());
		} else {
			insurance = new JLabel("");
		}
		insuranceText = new JTextField(insurance.getText());

		allergiesLabel = new JLabel("Allergies: ");
		if (user instanceof Patient) {
			allergies = new JLabel(((Patient) user).getAllergies());
		} else {
			allergies = new JLabel("");
		}
		allergiesText = new JTextField(allergies.getText());

		error = new JLabel("");
		errorFontSave = error.getFont().deriveFont(error.getFont().getStyle());
		errorFontError = error.getFont().deriveFont(
				error.getFont().getStyle() | Font.BOLD);
	}

	/**
	 * Adds everything to the panel
	 * @param c GridBagConstraints
	 */
	public void addToPanel(GridBagConstraints c) {
		c.gridy=0;
		c.gridwidth = 4; // $codepro.audit.disable numericLiterals
		center.add(error, c);
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridy++;

		addToPanelTop(c);

		c.gridwidth = 1;
		c.gridx = 0;
		c.gridy++;
		center.add(new JLabel("Name: "), c);
		c.gridx = 1;
		c.gridwidth = 3; // $codepro.audit.disable numericLiterals
		if (!canEdit) {
			center.add(name, c);
		} else {
			c.gridwidth = 1;
			c.ipadx = 70; // $codepro.audit.disable numericLiterals
			center.add(nameFirst, c);
			c.gridx++;
			center.add(nameMiddle, c);
			c.gridx++;
			center.add(nameLast, c);
			c.gridx-=2;
			c.ipadx = 0;
		}

		c.gridx = 0;
		c.gridy++;
		c.gridwidth = 1;
		center.add(dobLabel, c);
		c.gridx = 1;
		c.gridwidth = 3; // $codepro.audit.disable numericLiterals
		center.add(canEdit ? dobText : dob, c);

		c.gridx = 0;
		c.gridy++;
		c.gridwidth = 1;
		center.add(addressLabel, c);
		c.gridx = 1;
		c.gridwidth = 3; // $codepro.audit.disable numericLiterals
		center.add(canEdit ? addressText : address, c);

		c.gridx = 0;
		c.gridy++;
		c.gridwidth = 1;
		center.add(emailLabel, c);
		c.gridx = 1;
		c.gridwidth = 3; // $codepro.audit.disable numericLiterals
		center.add(canEdit ? emailText : email, c);

		c.gridx = 0;
		c.gridy++;
		c.gridwidth = 1;
		center.add(insuranceLabel, c);
		c.gridx = 1;
		c.gridwidth = 3; // $codepro.audit.disable numericLiterals
		center.add(canEdit ? insuranceText : insurance, c);

		c.gridx = 0;
		c.gridy++;
		c.gridwidth = 1;
		center.add(allergiesLabel, c);
		c.gridx = 1;
		c.gridwidth = 3; // $codepro.audit.disable numericLiterals
		center.add(canEdit ? allergiesText : allergies, c);

		addToPanelBottom(c);

		if (!(user instanceof Patient)) {

			dobLabel.setVisible(false);
			dobText.setVisible(false);
			dob.setVisible(false);
			emailLabel.setVisible(false);
			emailText.setVisible(false);
			email.setVisible(false);
			addressLabel.setVisible(false);
			addressText.setVisible(false);
			address.setVisible(false);
			allergiesLabel.setVisible(false);
			allergiesText.setVisible(false);
			allergies.setVisible(false);
			insuranceLabel.setVisible(false);
			insuranceText.setVisible(false);
			insurance.setVisible(false);
		}
	}

	/**
	 * Method addToPanelTop.
	 * @param c GridBagConstraints
	 */
	private void addToPanelTop(GridBagConstraints c) {
		if (newUser && admin) {
			c.gridwidth = 1;
			c.gridx = 1;
			center.add(userType, c);
		}
		if (admin) {
			c.gridx = 0;
			c.gridy++;
			center.add(active, c);
		}

		if (newUser && canEdit) {
			c.gridwidth = 1;
			c.gridx = 0;
			c.gridy++;
			center.add(new JLabel("Username: "), c);
			c.gridx = 1;
			c.gridwidth = 3; // $codepro.audit.disable numericLiterals
			center.add(usernameText, c);

			c.gridwidth = 1;
			c.gridx = 0;
			c.gridy++;
			center.add(new JLabel("Password: "), c);
			c.gridx = 1;
			c.gridwidth = 3; // $codepro.audit.disable numericLiterals
			center.add(passwordText, c);

			c.gridwidth = 1;
			c.gridx = 0;
			c.gridy++;
			center.add(new JLabel("Repeat Password: "), c);
			c.gridx = 1;
			c.gridwidth = 3; // $codepro.audit.disable numericLiterals
			center.add(password2Text, c);
		} else {
			c.gridwidth = 1;
			c.gridx = 0;
			c.gridy++;
			center.add(new JLabel("Username: "), c);
			c.gridx = 1;
			c.gridwidth = 3; // $codepro.audit.disable numericLiterals
			center.add(new JLabel(user.getUsername()), c);
		}
	}

	/**
	 * Method addToPanelBottom.
	 * @param c GridBagConstraints
	 */
	public void addToPanelBottom(GridBagConstraints c) {
		c.gridwidth = 1;
		c.gridy++;
		c.gridx = 1;
		save = new JButton("Save");
		if (canEdit) {
			center.add(save, c);
		}

		c.gridx++;
		reset = new JButton("Reset");
		if (canEdit) {
			center.add(reset,  c);
		}

		//skip a line
		c.gridy++;
		c.gridx = 0;
		c.gridwidth = 4; // $codepro.audit.disable numericLiterals
		center.add(new JLabel(" "));
		c.gridy++;

		center.add(new JLabel("*DOB must follow the form of the example: " +
		"March 20, 1990"), c);

		c.gridy++;
		center.add(new JLabel(" "));
		c.gridy++;

		//center.add(new JButton("View Patient's Appointments/Treatment Records"));
		history = new JButton("View Patient's Medical History");
		if (!newUser) {
			center.add(history, c);
		}
	}
}